//
//  XPIPAddress.swift
//  PPKit
//
//  Created by xiaopin on 2019/7/10.
//  Copyright © 2019 PPKit. All rights reserved.
//  https://gitee.com/xiaopindev/PPKit
//  https://github.com/xiaopindev
//  https://xiaopin.cnblogs.com

import UIKit

class XPIPAddress{
    private var _publicIP:String? = ""
    private var _operatorsIP:String? = ""
    private var _wifiIP:String? = ""
    
    //MARK: 单例类写法
    static let shared = XPIPAddress()
    private init(){
        self.publicIPAddress { (ip) in
            self._publicIP = ip
        }
        self._operatorsIP = self.operatorsIPAddress()
        self._wifiIP = self.wifiIPAddress()
    }
    
    //MARK: 属性
    var publicIP:String {
        get{
            return self._publicIP!
        }
    }
    
    var operatorsIP:String {
        get{
            return self._operatorsIP!
        }
    }
    
    var wifiIP:String {
        get{
            return self._wifiIP!
        }
    }
    
    //MARK: 方法
    /// 获得公网IP
    func publicIPAddress(backBlock: @escaping ((_ ipStr:String)->())){
        DispatchQueue.global().async {
            if let url = URL(string: "https://www.ip.cn/api/index?ip=&type=0") {
                let jsonStr = try? String(contentsOf: url, encoding: String.Encoding.utf8)
                let dict = pp_json_fromString(jsonStr ?? "")
                let ip = (dict?["ip"] as? String) ?? ""
                print("当前公网IP:\(ip)")
                DispatchQueue.main.async {
                    backBlock(ip)
                }
            }else {
                print("获得公网IP URL 转换失败")
            }
        }
    }
    
    /// 获取当前设备运营商IP
    func operatorsIPAddress() -> String? {
        var addresses = [String]()
        var ifaddr : UnsafeMutablePointer<ifaddrs>? = nil
        if getifaddrs(&ifaddr) == 0 {
            var ptr = ifaddr
            while (ptr != nil) {
                let flags = Int32(ptr!.pointee.ifa_flags)
                var addr = ptr!.pointee.ifa_addr.pointee
                if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) {
                    if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {
                        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                        if (getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count),nil, socklen_t(0), NI_NUMERICHOST) == 0) {
                            if let address = String(validatingUTF8:hostname) {
                                addresses.append(address)
                            }
                        }
                    }
                }
                ptr = ptr!.pointee.ifa_next
            }
            freeifaddrs(ifaddr)
        }
        return addresses.first
    }
    
    //获取本机无线局域网ip
    func wifiIPAddress() -> String? {
        
        var address: String?
        var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
        guard getifaddrs(&ifaddr) == 0 else {
            return nil
        }
        guard let firstAddr = ifaddr else {
            return nil
        }
        
        for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
            let interface = ifptr.pointee
            // Check for IPV4 or IPV6 interface
            let addrFamily = interface.ifa_addr.pointee.sa_family
            if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
                // Check interface name
                let name = String(cString: interface.ifa_name)
                if name == "en0" {
                    // Convert interface address to a human readable string
                    var addr = interface.ifa_addr.pointee
                    var hostName = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                    getnameinfo(&addr,socklen_t(interface.ifa_addr.pointee.sa_len), &hostName, socklen_t(hostName.count), nil, socklen_t(0), NI_NUMERICHOST)
                    address = String(cString: hostName)
                }
            }
        }
        
        freeifaddrs(ifaddr)
        return address
    }
}
